/**
 * 函数防抖
 * @method debunoce
 * @param {Number} time 间隔时间 单位秒
 * @param { Function } callback 回调函数 time秒后没有再次触发则执行
 *
 */
function debunoce(time = 60, callback) {
  let timer = null;
  return function (...args) {
    let _this = this;
    if (timer) clearTimeout(timer);
    timer = setTimeout(function () {
      callback.apply(_this, args);
    }, time);
  };
}

/**
 * 节流函数
 * @method throttle
 * @param {Number} deply 等待事件
 * @param { Function } fn 回调函数
 * @param { Boolean } immediate 立即执行?
 */
function throttle(deply = 60, fn) {
  let flag = true;
  return function (...args) {
    if (!flag) return;
    fn(...args);
    flag = false;
    setTimeout(() => {
      flag = true;
    }, deply);
  };
}

/***
 * 数组按某个元素属性进分组
 * @method groupArr
 * @param {Array} arr 要分组的数组
 * @param {String} key 需要按这个key的值进行分组 'a'
 * @return {Object} 分组后的对象 [{a:1},{b:2},...]=> {a:[{a:1}],b:[{b:2}],...}
 */
function groupArr(arr, key) {
  return arr.reduce((pre, cur) => {
    if (!pre[cur[key]]) {
      pre[cur[key]] = [];
    }
    pre[cur[key]].push(cur);
    return pre;
  }, {});
}

/**
 * 数组去重
 * @method arrDuremove
 * @param {Array} arr 要去重的数组
 * @returns {Array} 去重后的数组 [1,1,1,2,2,2,3,4,5,3,2,4,5,1,4,5,3]=>[1, 2, 3, 4, 5]
 */
function arrDuremove(arr) {
  if (!Array.isArray(arr)) return arr;
  return arr.reduce((pre, cur) => {
    if (!pre.includes(cur)) {
      pre.push(cur);
    }
    return pre;
  }, []);
}

/**
 * 数组计数
 * @method arrayCount
 * @param {Array} arr 要计数的数组
 * @return {object} [1,1,1,2,2,2,3,4,5,3,2,4,5,1,4,5,3]=>{1: 4, 2: 4, 3: 3, 4: 3, 5: 3}
 */
function arrayCount(arr) {
  if (!Array.isArray(arr)) return arr;
  return arr.reduce((pre, cur) => {
    if (!(cur in pre)) {
      pre[cur] = 1;
    } else {
      pre[cur]++;
    }
    return pre;
  }, {});
}

/* 柯里化 */
/**
 * 实现以下
 * const foo = curry((a,b,c,d)=>{
 * console.log(a,b,c,d)
 * })
 *
 * foo(1)(2)(3)(4) // 1 2 3 4
 * foo(1)(2)(3)// 不返回
 * const f =  foo(1)(2)(3)
 *
 * f(5) // 1 2 3 5
 */

const curry = (func) => {
  // 因为foo是一个函数的调用,curry调用的时候,传入的是一个函数,所哟,func就是传入的那个函数
  // foo(1)(2)(3)调用达不到四次时,会将之前传瑞的参数进行保存,然后当最后一次调用时候,才会
  // 将foo内的回调函数进行调用,fn就是foo内部的回调函数

  const fn = (...allArgs) =>
    allArgs.length >= func.length
      ? func(...allArgs)
      : (...arg) => fn(...allArgs, ...arg);
  return fn;
};

/* const foo = curry((a,b,c,d)=>{
  console.log(a,b,c,d)
  })
foo(1)(2)(3)(4) // 1 2 3 4
foo(1)(2)(3)// 不返回
const f =  foo(1)(2)(3)
f(5) // 1 2 3 5
 */